
#include "stdafx.h"
#include "AnimBillboardSceneNode.h"
#include "Application.h"

#include "ISceneNode.h"
#include "ISceneManager.h"
#include "IFileSystem.h"
#include "IO/FileSystem/BinaryFile.h"
#include "Lib2D/SpriteManager.h"
#include "SceneManager/FpsMaterial.h"
#include "SceneManager/FpsSceneManager.h"
#include "SceneManager/FpsCommonGLMaterialRenderer.h"
#include "Game/Utils/Utils.h"

using namespace irr;
using namespace irr::video;
using namespace irr::core;
// -------------------------------------------------------------------------------
// Animated billboard Scene Node implementation
// -------------------------------------------------------------------------------

//! constructor
AnimBillboardSceneNode::AnimBillboardSceneNode(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id)
	: CBillboardSceneNode(0, vector3df(0.0, 0.0, 0.0), dimension2d<f32>(20, 20))
{
	m_sprite = 0;
	m_spriteInstance = 0;

	setSize(1.0f);
}

AnimBillboardSceneNode::~AnimBillboardSceneNode()
{
	if(m_spriteInstance)
	{
		delete m_spriteInstance;
		m_spriteInstance = NULL;
	}

	if( m_sprite )
	{		
		m_sprite = NULL;
	}
}

//! pre render event
void AnimBillboardSceneNode::OnRegisterSceneNode()
{
	//if (!strcmp(getName(), "boss_fire")) {
	//	int _debug = 1;
	//}
	/*
	if (IsVisible)
	{
		SceneManager->registerNodeForRendering(this, 0, (void*)0, irr::scene::ESNRP_AUTOMATIC);
	}*/
	if (m_spriteInstance) {
		CBillboardSceneNode::OnRegisterSceneNode();
	}
}

void AnimBillboardSceneNode::update(float timeStamp)
{
	if(m_spriteInstance)
	{
		m_spriteInstance->Update(timeStamp);
	}
}

//! render
void AnimBillboardSceneNode::render(void* renderData)
{
//if (!strcmp(getName(), "boss_fire")) {
//	int _debug = 1;
//}
	if(m_spriteInstance)
	{				
		m_spriteInstance->Paint(getAbsolutePosition());		
	}
}


//! returns the axis aligned bounding box of this node
const core::aabbox3d<f32>& AnimBillboardSceneNode::getBoundingBox() const
{
	return BBox;
}

//! sets the size of the billboard
void AnimBillboardSceneNode::setSize(const f32 size)
{
	Size = size;

	if (Size == 0.0f)
		Size = 1.0f;

	if (m_spriteInstance)
		m_spriteInstance->SetScale(Size);

	f32 avg = Size/3;
	BBox.MinEdge.set(-avg,-avg,-avg);
	BBox.MaxEdge.set(avg,avg,avg);
}

//! sets the sprite instance to render
void AnimBillboardSceneNode::LoadSprite(const char* spriteName)
{
	m_spritename = spriteName;

	if(m_spriteInstance)
	{
		delete m_spriteInstance;
		m_spriteInstance = NULL;
	}

	if(m_spritename != "")
	{
		bool isLinear = true;
		if( ::stricmp("hintbb.bsprite",spriteName ) == 0 )
		{
			isLinear = false;
		}
		if( 1 == CSpriteManager::instance()->LoadSprite(spriteName,false,isLinear))
		{
			m_sprite = CSpriteManager::instance()->GetSprite(spriteName);
			if(m_sprite)
			{				
				m_spriteInstance = NEW CSpriteInstance(0, 0, m_sprite);
				//for alpha test
				SetBillboardMaterialType(irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
			}
			
			if (m_spriteInstance)
			{
				m_spriteInstance->SetScale(Size);
			}
		}
	}
}

void AnimBillboardSceneNode::UnloadSprite()
{
	if(m_spriteInstance)
	{
		delete m_spriteInstance;
		m_spriteInstance = NULL;
		m_sprite = NULL;
		m_spritename = "";
	}
}

////! Writes attributes of the scene node.
//void AnimBillboardSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
//{
//	ISceneNode::serializeAttributes(out, options);
//
//	out->addFloat("Width", Size.Width);
//	out->addFloat("Height", Size.Height);
//}
//
//
////! Reads attributes of the scene node.
//void AnimBillboardSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
//{
//	ISceneNode::deserializeAttributes(in, options);
//
//	float width = in->getAttributeAsFloat("Width");
//	float height = in->getAttributeAsFloat("Height");
//	setSize(dimension2df(width, height));
//}

u32 AnimBillboardSceneNode::getMaterialCount () const
{
	if (m_spriteInstance && m_spriteInstance->m_pSpr)
		return 1;
	else
		return 0;
}

SMaterial& AnimBillboardSceneNode::getMaterial (u32 num)
{
	ASSERT(m_spriteInstance && m_spriteInstance->m_pSpr);
	return *m_spriteInstance->m_pSpr->m_pMaterial;
}

AnimBillboardSceneNode* AnimBillboardSceneNode::clone ()
{
	AnimBillboardSceneNode* result = new AnimBillboardSceneNode(getParent(), SceneManager, -1);
	result->Size = Size;
	result->LoadSprite(m_spritename.c_str());
	//result->LoadTexture(m_texturename.c_str());
	result->cloneMembers(this);
	result->SceneManager = SceneManager;
	result->m_spriteInstance->SetAnim(m_spriteInstance->GetAnimation() );

	return result;
}

void AnimBillboardSceneNode::OnMaterialChanged()
{

}

void AnimBillboardSceneNode::SetBillboardMaterialType(irr::video::E_MATERIAL_TYPE type)
{

	irr::video::SMaterial& sprMaterial = getMaterial(0);

	sprMaterial.setMaterialType(type);
	sprMaterial.setFlag(irr::video::EMF_LIGHTING, false);
	sprMaterial.setFlag(irr::video::EMF_ZBUFFER, true);

	if(type==EMT_NONTRANSPARENT_ADDITIVE_MODULATE)
	{						
		sprMaterial.setFlag(irr::video::EMF_PER_VERTEX_MATERIAL_COLOR, false);					
		sprMaterial.setFlag(irr::video::EMF_ZWRITE_ENABLE, false);	
		sprMaterial.setMaterialTypeParam(2, FPS_MATERIAL_RENDER_PRIORITY_ADDITIVE);
		sprMaterial.setDiffuseColor(irr::video::SColor(255, 255, 255, 255));	
		SetNodeRenderingLayer(this, RL_HIT_EFFECTS);
	}
	else
	{		
		sprMaterial.setFlag(irr::video::EMF_ZWRITE_ENABLE, true);		
	}
}
